{
  LW Nodes -- LightWave Shader Nodes

  The NodeHandler provides a Node based aproach to most texturing or image
  based/procedural/gradient modifyers within LightWave®.

  Based on lwnodes.h which is:
  Copyright 2005, NewTek, Inc.
}

{
  Copyright 2012, Jameel Halabi

  This unit is part of the BlaiseWave wrapper,
  which is licensed under the BSD 2-Clause license (see licenses/license.txt).
}
unit LW_Nodes;

{$mode objfpc}{$H+}

interface

uses
  LW_Types      ,
  LW_Meshes     ,
  LW_Envel      ,
  LW_Server     ,
  LW_Handler    ,
  LW_Render     ,
  LW_Txtr       ,
  LW_Instancing ;

const
  LWNODE_HCLASS        = 'NodeHandler'   ;
  LWNODE_ICLASS        = 'NodeInterface' ;
  LWNODE_GCLASS        = 'NodeGizmo'     ;
  LWNODECLASS_VERSION  = 3               ;

  LWNODEFUNCS_GLOBAL         = 'NodeFuncs'         ;
  LWNODEINPUTFUNCS_GLOBAL    = 'NodeInputFuncs 3'  ;
  LWNODEOUTPUTFUNCS_GLOBAL   = 'NodeOutputFuncs 2' ;
  LWNODEUTILITYFUNCS_GLOBAL  = 'NodeUtilityFuncs'  ;
  LWNODEDRAWFUNCS_GLOBAL     = 'NodeDrawFuncs'     ;

  // Predefined server strings for SRVTAG_NODECONTEXT server tag.
  NCON_ALL  = 'All'      ; // Node is available in all contexts.
  NCON_MESH = 'Mesh'     ; // Node is available in contexts where a physical mesh is provided.
  NCON_SPOT = 'Spot'     ; // Node is available in contexts where virtual spot geometry is provided.
  NCON_SURF = 'Surface'  ; // Node is available in contexts where virtual or real surface geometry is provided. A surface requires proper normals.
  NCON_RAYT = 'Raytrace' ; // Node is available in contexts where ray-tracing functions are provided.

  // The type of the node preview for the nodes editor.
  // enum NodePreviewType
  NPT_RENDER = 0 ;
  NPT_CUSTOM = 1 ;
  NPT_OFF    = 2 ;

  // Node input/output types.
  // enum ConnectionType
  NOT_COLOR    = 1 ;
  NOT_SCALAR   = 2 ;
  NOT_VECTOR   = 3 ;
  NOT_INTEGER  = 4 ;
  NOT_FUNCTION = 5 ;
  NOT_MATERIAL = 6 ;
  NOT_CUSTOM   = 1024 ;

  // Input event types.
  // enum LWNodalEvent
  NIE_CONNECT          = 0 ; // When an output is connected to this input.
  NIE_DISCONNECT       = 1 ; // When the output was disconnected from this input.
  NIE_INPUTNODEDESTROY = 2 ; // When the node connected to this input was destroyed.

  // Node flags. Returned by LWNodeHandler->flags
  NF_TRANSP          = 1 shl 0  ;  // This flag should be set if a material node might have transparency
  NF_SINGLE_THREADED = 1 shl 30 ;  // Force single-threaded evaluation (for nodal displacement only)

  // Blending modes.
  // enum BlendingMode
  Blend_Normal       =  0  ;
  Blend_Additive     =  1  ;
  Blend_Subtractive  =  2  ;
  Blend_Multiply     =  3  ;
  Blend_Screen       =  4  ;
  Blend_Darken       =  5  ;
  Blend_Lighten      =  6  ;
  Blend_Difference   =  7  ;
  Blend_Negative     =  8  ;
  Blend_ColorDodge   =  9  ;
  Blend_ColorBurn    = 10  ;
  Blend_Red          = 11  ;
  Blend_Green        = 12  ;
  Blend_Blue         = 13  ;

type
  PNodeInput     =  Pointer ;
  PNodeOutput    =  Pointer ;
  PNode          =  Pointer ;
  PNodeData      =  Pointer ;
  PNodeValue     =  Pointer ;

  PLWNodalAccess = ^TLWNodalAccess ;
  TLWNodalAccess = record
    Illuminate              : TLWIlluminateFunc             ;
    IlluminateSample        : TLWIlluminateSampleFunc       ;
    RayTrace                : TLWRayTraceFunc               ;
    RayCast                 : TLWRayCastFunc                ;
    RayShade                : TLWRayShadeFunc               ;
    RayTraceMode            : TLWRayTraceModeFunc           ;

    Bounces                 : Integer                       ;

    SourceID                : PLWItem                       ;

    ObjID                   : PLWItem                       ;
    PolNum                  : Integer                       ;

    Verts                   : array[0..3] of PLWPnt         ;
    Weights                 : array[0..3] of Single         ;
    VertsWPos               : array[0..3 , 0..2] of Single  ;
    Polygon                 : PLWPol                        ;

    IncomingEta             : Double                        ; // Incoming refraction index.
    ResourceContextIndex    : Integer                       ; // Current CPU thread running.
    Flags                   : Integer                       ;

    RandomData              : PRandomFloatData              ;
    RandomFloat             : TLWRandomFloatFunc            ;

    IlluminateNormal        : TLWIlluminateNormalFunc       ;
    IlluminateSampleNormal  : TLWIlluminateSampleNormalFunc ;

    Subsx, subsy            : Double                        ;

    RayDir                  : TLWDVector                    ;

    RayTraceData            : TLWRayTraceDataFunc           ;
    RayTraceShade           : TLWRayTraceShadeFunc          ;
    Render                  : PLWRenderData                 ;

    GetVal                  : TLWBufferGetValFunc           ;
    SetVal                  : TLWBufferSetValFunc           ;

    // Added Version 3 for AnimUV cycling.

    Outsize                 : Integer                       ;
    // Indexs To Original Polygone Vertex Index and Prespective Weights.
    VertexIndexes           : PLWVertexIndexes              ;

    InstanceID              : PLWItemInstance               ;

    SamplerState            : PLWSamplerState               ;
    GetSamplerRange         : TLWGetSamplerRangeFunc        ;
    GetSample2D             : TLWGetSample2DFunc            ;
    getSample1D             : TLWGetSample1DFunc            ;
  end;

  PLWNodalMaterial = ^TLWNodalMaterial ;
  TLWNodalMaterial = record
    Diffuse       : TLWDVector ;
    Specular      : TLWDVector ;
    Reflection    : TLWDVector ;
    Refraction    : TLWDVector ;
    Transparency  : Double     ;
  end;

  PLWNodeDrawFuncs = ^TLWNodeDrawFuncs ;
  TLWNodeDrawFuncs = record
    DrawPixel    : procedure
                   (       NodeID : PNode   ;
                           C      : Integer ;
                           X      : Integer ;
                           Y      : Integer ) ;
    DrawRGBPixel : procedure
                   (       NodeID : PNode   ;
                           R      : Integer ;
                           G      : Integer ;
                           B      : Integer ;
                           X      : Integer ;
                           Y      : Integer ) ;
    DrawLine     : procedure
                   (       NodeID : PNode   ;
                           C      : Integer ;
                           X      : Integer ;
                           Y      : Integer ;
                           X2     : Integer ;
                           Y2     : Integer ) ;
    DrawBox      : procedure
                   (       NodeID : PNode   ;
                           C      : Integer ;
                           X      : Integer ;
                           Y      : Integer ;
                           W      : Integer ;
                           H      : Integer ) ;
    DrawRGBBox   : procedure
                   (       NodeID : PNode   ;
                           R      : Integer ;
                           G      : Integer ;
                           B      : Integer ;
                           X      : Integer ;
                           Y      : Integer ;
                           W      : Integer ;
                           H      : Integer ) ;
    TextWidth    : function
                   (       NodeID : PNode   ;
                           S      : PChar   ) : Integer ;
    TextHeight   : function
                   (       NodeID : PNode   ;
                           S      : PChar   ) : Integer ;
    DrawText     : procedure
                   (       NodeID : PNode   ;
                           S      : PChar   ;
                           C      : Integer ;
                           X      : Integer ;
                           Y      : Integer ) ;
    BlitNode     : procedure
                   (       NodeID : PNode   ) ;
  end;

  TNodeInputEvent = function
                    (       UserData       : Pointer     ;
                            NodeInputID    : PNodeInput  ;
                             // Originally enum LWNodalEvent
                            NodalEvent     : Integer     ;
                            // Originally enum ConnectionType
                            ConnectionType : Integer     ) : Integer;

  PLWNodeOGLTextureOutput = ^TLWNodeOGLTextureOutput;
  TLWNodeOGLTextureOutput = record
    ImageID   : PLWImage              ;
    UVCoords  : array[0..1] of Single ;
    Val       : TLWFVector            ;
  end;

  // Node handler activation.
  PLWNodeHandler = ^TLWNodeHandler ;
  TLWNodeHandler = record
    Inst        : PLWInstanceFuncs;
    Item        : PLWItemFuncs    ;
    Rend        : PLWRenderFuncs  ;

    { Evaluation function receives the LWNodalAccess structure.
      NodeOutputID is the output belonging to this node, and which is being
      currently asked the value from.
      NodeValue is the value you need to set with the output functions
      when setting a value for this evaluation.                              }
    Evaluate      : procedure
                    (        Instance     : PLWInstance    ;
                             Access       : PLWNodalAccess ;
                             NodeOutputID : PNodeOutput    ;
                             Value        : PNodeValue     ) ;
    // CustomPreview is called when the node has NPT_CUSTOM preview type set.
    CustomPreview : procedure
                    (        Instance     : PLWInstance    ;
                             Width        ,
                             Height       : Integer        ) ;
  end;

  // Functions for node inputs.
  PLWNodeInputFuncs = ^TLWNodeInputFuncs ;
  TLWNodeInputFuncs = record
    Create   : function
               (       NodeID         : PNode           ;
                       ConnectionType : Integer         ; // Originally enum ConnectionType
                 const Name           : PChar           ;
                       NodeInputEvent : TNodeInputEvent ) : PNodeInput ;
    // Destroy an input from the node.
    Destroy   : procedure
                (       NodeID         : PNode           ;
                        NodeInputID    : PNodeInput      ) ;
    // Evaluate an input.
    // The value filled with a value received from the node evaluated,
    // according to the type of the input evaluated.
    Evaluate  : function
                (       NodeInputID    : PNodeInput      ;
                        Access         : PLWNodalAccess  ;
                        Value          : Pointer         ) : Integer ;
    // Check if this input is connected to.
    Check     : function
                (       NodeInputID    : PNodeInput      ) : Integer ;
    // Get the first input from a node.
    First     : function
                (       NodeID         : PNode           ) : PNodeInput ;
    // Get the next input.
    Next      : function
                (       NodeInputID    : PNodeInput      ) : PNodeInput ;
    // Get the previous input.
    Previous  : function
                (       NodeInputID    : PNodeInput      ) : PNodeInput ;
    NumInputs : function
                (       NodeID         : PNode           ) : Integer    ;
    // Get an input by it's index number.
    // The index number of the first input is 1.
    ByIndex   : function
                (       NodeID         : PNode           ;
                        Index          : Integer         ) : PNodeInput ;
    // Get the index number of the input.
    // If the input doesn't belong to this node, returns 0.
    // The index number of the first input is 1.
    GetIndex  : function
                (       NodeID         : PNode           ;
                        NodeInputID    : PNodeInput      ) : Integer    ;

    // Disconnect any output from this input.
    Disconnect : procedure
                (       NodeID         : PNode           ;
                        NodeInputID    : PNodeInput      ) ;
    // Returns the node this input belongs to.
    Node       : function
                (       NodeInputID    : PNodeInput      ) : PNode      ;
    // Returns the NodeOutputID this input is connected to.
    ConnectedOutput : function
                      (       NodeInputID    : PNodeInput      ) : PNodeOutput ;
    // Returns the name of the NodeInputID.
    Name      : function
                (       NodeInputID    : PNodeInput      ) : PChar       ; // const
    // Create custom connection type.
    CreateCustom : function
                   (       NodeID         : PNode           ;
                           ConnectionType : Integer         ; // Originally enum ConnectionType
                           Name           : PChar           ;
                           NodeInputEvent : TNodeInputEvent ;
                           VendorID       ,
                           TypeID         : UInt32          ) : PNodeInput ;
  end;

  PLWNodeOutputFuncs = ^TLWNodeOutputFuncs ;
  TLWNodeOutputFuncs = record
    // Create a new output for the node.
    Create   : function
               (       NodeID         : PNode           ;
                       ConnectionType : Integer         ; // Originally enum ConnectionType
                 const Name           : PChar           ) : PNodeOutput ;
    // Destroy an output from the node.
    Destroy  : procedure
               (       NodeID         : PNode           ;
                       NodeOutputID   : PNodeOutput     ) ;
    // Set the value for the output being evaluated.
    // Call from the node evaluation function when rendering.
    SetValue : procedure
               (       NodeValue     : PNodeValue       ;
                       Value         : Pointer          ) ;
    // Get the pointer to the value cast to the input functions evaluate call.
    GetValue : function
               (       NodeValue     : PNodeValue       ) : Pointer ;

    // Get the type of the connection the value is coming from.
    GetType   : function
                (       NodeValue     : PNodeValue       ) : Integer ; // Originally returned enum ConnectionType
    // Get the first output from a node.
    First     : function
                (       NodeID         : PNode           ) : PNodeOutput ;
    // Get the next output.
    Next      : function
                (       NodeOutputID   : PNodeOutput     ) : PNodeOutput ;
    // Get the previous output.
    Previous  : function
                (       NodeOutputID   : PNodeOutput     ) : PNodeOutput ;
    // Get the number of outputs for this node.
    NumInputs : function
                (       NodeID         : PNode           ) : Integer     ;
    // Get an output by it's index number.
    // The index number of the first output is 1.
    ByIndex   : function
                (       NodeID         : PNode           ;
                        Index          : Integer         ) : PNodeOutput ;
    // Get the index number of the output.
    // If the output doesn't belong to this node, returns 0.
    // The index number of the first output is 1.
    GetIndex  : function
                (       NodeID         : PNode           ;
                        NodeOutputID   : PNodeOutput     ) : Integer    ;

    // Returns the node this output belongs to.
    Node      : function
                (       NodeOutputID   : PNodeOutput     ) : PNode      ;

    // Returns the name of the NodeOutputID.
    Name      : function
                (       NodeOutputID   : PNodeOutput     ) : PChar      ; // const
    // Create custom connection type.
    CreateCustom : function
                   (       NodeID         : PNode           ;
                           ConnectionType : Integer         ; // Originally enum ConnectionType
                           Name           : PChar           ;
                           VendorID       ,
                           TypeID         : UInt32          ) : PNodeOutput ;
  end;

  PLWNodeFuncs =^TLWNodeFuncs ;
  TLWNodeFuncs = record
    { Get the name for the node in the editor.
      Will be the name of the node, with it's index number added to it.
      Ie. "Texture (1)", etc.                                               }
    NodeName       : function
                   (         NodeID         : PNode           ) : PChar          ; // const
    // Get the server name for this node.
    ServerUserName : function
                   (         NodeID         : PNode           ) : PChar          ; // const
    // Get the channel group for this node.
    ChanGrp        : function
                   (         NodeID         : PNode           ) : PLWChanGroup   ;
    // Set the color for this node.
    SetNodeColor   : procedure
                   (         NodeID         : PNode           ;
                             RGB            : array {[0..2]} of Integer ) ;
    // Set the color for this node. using separated R, G and B values.
    SetNodeColor3  : procedure
                   (         NodeID         : PNode           ;
                             R              ,
                             G              ,
                             B              : Integer         ) ;
    // Set the preview type for this node.
    SetNodePreviewType : procedure
                         (   NodeID          : PNode            ;
                             // Originally enum NodePreviewType
                             NodePreviewType : Integer          ) ;

    // Do an immediate interface update for this node.
    // Draws the preview only for this node.
    UpdateNodePreview  : procedure
                         (   NodeID          : PNode            ) ;
  end;

  PLWNodeUtilityFuncs = ^TLWNodeUtilityFuncs ;
  TLWNodeUtilityFuncs = record
    // Function to use the built-in blending modes.
    Blend             : procedure
                        (        Result_      ,
                                 BG           ,
                                 FG           : TLWDVector   ;
                                 Alpha        : Double       ;
                                 // Originally enum BlendingMode
                                 BlendingMode : Integer )    ;

    // Scale and position vectors will be filled with the automatic values.
    NodeAutosize       : procedure
                         (        NodeID       : PNode        ;
                                  Scale        ,
                                  Position     : TLWDVector   ) ;
    PlanarMapping      : procedure
                         (        TPos         : TLWDVector   ;
                                  Axis         : Integer      ;
                                  U            ,
                                  V            : PDouble      ) ;
    SphericalMapping   : procedure
                         (        TPos         : TLWDVector   ;
                                  Axis         : Integer      ;
                                  U            ,
                                  V            : PDouble      ) ;
    CylindricalMapping : procedure
                         (        TPos         : TLWDVector   ;
                                  Axis         : Integer      ;
                                  U            ,
                                  V            : PDouble      ) ;
    // The axis for cubic mapping is the major axis the surface normal points to.
    CubicMapping       : procedure
                         (        TPos         : TLWDVector   ;
                                  Axis         : Integer      ;
                                  U            ,
                                  V            : PDouble      ) ;
    FrontMapping       : procedure
                         (        TPos         : TLWDVector   ;
                                  PixelAspect  : Double       ;
                                  U            ,
                                  V            : PDouble      ;
                                  CameraMatrix : array {[0..3 , 0..3]} of Double ) ;
    ReflectionMapping  : procedure
                         (        SeamAngle    : Double       ;
                                  Direction    : TLWDVector   ;
                                  U            ,
                                  V            : PDouble      ) ;
    // Returns true if successful.
    UVMapping          : function
                         ( const  UVMapName    : PChar          ;
                                  Accesss      : PLWNodalAccess ;
                                  U            ,
                                  V            : PDouble        ) : Integer ;
    // Build the transformation matrix for front projection mapping to use.
    BuildCameraMatrix  : procedure
                         (        InTime       : TLWTime                         ;
                                  CameraID     : PLWItem                         ;
                                  CameraMatrix : array {[0..3 , 0..3]} of Double ) ;
  end;


implementation

end.

